#ifndef SERVER_HPP  
#define SERVER_HPP 
#include"data.hpp"
#include"httplib.h"

                                                                 
extern cloud::DataManger *_data;
namespace cloud{
   class Service{
        private:
        int _server_port;                 //实现通信端口号，ip,下载文件,比方下载一个文件  请求0.0.0.0:8080/download/txt.dat
        std::string _server_ip;
        std::string _download_prefix;     //           /download/
        httplib::Server _server;          //使用httplib搭建服务器
        private:
       static std::string TimetoStr(time_t t){
           std::string tmp=std::ctime(&t);
           return tmp;
        }
      static std::string GetETag(const BackupInfo &info)
      {
       FileUtil fu(info.real_path);
       std::string etag=fu.FileName();
       etag+="-";
       etag+=std::to_string(info.fsize);
       etag+="-";
       etag+=std::to_string(info.mtime);
       return etag;
      }



       static void Upload(const httplib::Request&req,httplib::Response &rsp)//实现上传功能
        {
           auto ret=req.has_file("file");
           //std::cout<<ret;
           if(ret==false){
               rsp.status=400;
               return ;

           }
           
           const auto& file=req.get_file_value("file");
           std::string back_dir=Config::GetInstance()->GetBackDir();
           std::string realpath=back_dir+FileUtil(file.filename).FileName();
           FileUtil fu(realpath);
           fu.SetContent(file.content);
           BackupInfo info;
           info.NewBackupInfo(realpath);
           _data->Insert(info);
           return ;



        }
        static void ListShow(const httplib::Request&req,httplib::Response &rsp)//实现页面展示功能
        {
           std::vector<BackupInfo>arry;
           _data->GetAll(&arry);
           std::stringstream ss;
           ss<<"<html><head><tille>Download</title></head>";
           ss<<"<body><h1>Download</h1><table>";
           for(auto &a:arry){
           ss<<"<tr>";
           std::string filename=FileUtil(a.real_path).FileName();
           ss<<"<td><a href='"<<a.url<<"'>"<<filename<<"</a></td>";
           ss<<"<td align='right'>"<<TimetoStr(a.mtime)<<"</td>";
           ss<<"<td align='right'>"<<a.fsize/1024<<"k</td>";
           ss<<"</tr>";
           }
           ss<<"</table></body></html>";
           rsp.body=ss.str();
           rsp.set_header("Content-Type","text/html");
           rsp.status=200;
           return ;

        }
        static void Download(const httplib::Request&req,httplib::Response &rsp)//实现下载功能
        {
          BackupInfo info;
          _data->GetOneByURL(req.path,&info);

          if(info.pack_flag==true)
          {
             FileUtil fu(info.pack_path);
             fu.UnCompress(info.real_path);
                fu.Remove();
                info.pack_flag=false;
                _data->Update(info);
          }
                 //FileUtil fu(info.real_path);
                // fu.GetContent(&rsp.body);

            bool retrans=false;
            std::string  old_etag;
            if(req.has_header("If-Range")){
              old_etag=req.get_header_value("If-Range");
              if(old_etag==GetETag(info))
              {retrans=true;}
            }


          FileUtil fu(info.real_path);
        if(retrans==false)
        {fu.GetContent(&rsp.body);
         rsp.set_header("Accept-Rangers","bytes");
        rsp.set_header("ETag",GetETag(info));
        rsp.set_header("Content-Type","application/octet-stream");
        rsp.status=200;
        return ;

        }
        else
        {
         fu.GetContent(&rsp.body);
        rsp.set_header("Accept-Rangers","bytes");
        rsp.set_header("ETag",GetETag(info));
        rsp.set_header("Content-Type","application/octet-stream");
        rsp.status=206;
        }






        }
        public:
        Service()
        {
        Config *config=Config::GetInstance();      //获取配置信息端口号，ip,下载前缀
        _server_port=config->GetServerPort();
        _server_ip=config->GetServerIp();
        _download_prefix=config->GetDownloadPrefix();
         }



        bool RunModule()
        {               
          _server.Post("/upload",Upload);       //如果在浏览器输入   0.0.0.0:8080/upload    就执行上传请求
          _server.Get("/listshow",ListShow);    //如果在浏览器输入   0.0.0.0:8080/listshow    就执行获取页面请求   
          _server.Get("/",ListShow);            //如果在浏览器输入   0.0.0.0:8080/   就执行获取页面请求   
          std::string download_url=_download_prefix+"(.*)";//下载路径可能发生变化，方便修改，点匹配除"\n"和"\r"之外的任何单个字符。
        //                                                 *匹配前面的子表达式任意次。
          _server.Get(download_url,Download);            //如果在浏览器输入   0.0.0.0:8080/download/tex.dat    就执行获取文件下载请求   
          _server.listen(_server_ip.c_str(),_server_port);       //tcp监听，相当于建立好链接
          return true;

        }


   };


}

#endif